package org.darkforest.common.util;


//import com.sun.image.codec.jpeg.JPEGEncodeParam;
//import com.sun.image.codec.jpeg.JPEGImageEncoder;
import org.apache.http.util.LangUtils;
import org.darkforest.common.logger.Logger;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;

/**
 * Created by valentina on 15/2/10.
 * 图片压缩工具类
 */
public class PicCompressUtil {
    private File file = null;           // 文件对象
    private String inputDir;            // 输入图路径
    private String outputDir;           // 输出图路径
    private String inputFileName;       // 输入图文件名
    private String outputFileName;      // 输出图文件名
    private int outputSize = 1280;      // 默认输出图片宽/高
    private boolean proportion = true;  // 是否等比缩放标记(默认为等比缩放)

    public PicCompressUtil() { // 初始化变量
        inputDir = "";
        outputDir = "";
        inputFileName = "";
        outputFileName = "";
        outputSize = 1280;
    }

    public void setInputDir(String inputDir) {
        this.inputDir = inputDir;
    }

    public void setOutputDir(String outputDir) {
        this.outputDir = outputDir;
    }

    public void setInputFileName(String inputFileName) {
        this.inputFileName = inputFileName;
    }

    public void setOutputFileName(String outputFileName) {
        this.outputFileName = outputFileName;
    }

    public void setOutputSize(int outputSize) {
        this.outputSize = outputSize;
    }

    public void setWidthAndHeight(int size) {
        this.outputSize = size;
    }

    /**
     * 获得图片大小
     *
     * @param path ：图片路径
     * @return
     */
    public long getPicSize(String path) {
        file = new File(path);
        return file.length();
    }

    /**
     * 获取图片长宽尺寸
     *
     * @param path
     * @return 长宽相等时返回1*1，否则返回width*height
     */
    public static String getPicWH(String path) {
        Integer width = 1;
        Integer height = 1;
        try {
            //获得源文件
            File file = new File(path);
            if (!file.exists()) {
                return "";
            }
            Image img = ImageIO.read(file);
            // 判断图片格式是否正确
            if (img.getWidth(null) == -1) {
                return "";
            } else {
                width = img.getWidth(null);
                height = img.getHeight(null);
                //长宽相等时返回1*1
                if (LangUtils.equals(width, height)) {
                    width = 1;
                    height = 1;
                }
            }
        } catch (IOException ex) {
            Logger.error(PicCompressUtil.class, "Exception while calculate picture's width and height. {}", ex);
        }

        return width + "x" + height;
    }

    /**
     * 图片处理
     */
    public String compressPic() {
        try {
            //获得源文件
            file = new File(inputDir + inputFileName);
            if (!file.exists()) {
                return "";
            }
            Image img = ImageIO.read(file);
            // 判断图片格式是否正确
            if (img.getWidth(null) == -1) {
                Logger.debug(PicCompressUtil.class, "无法读取图片!");
                return "no";
            } else {
                int newWidth;
                int newHeight;
                // 判断是否是等比缩放
                if (this.proportion) {
                    // 为等比缩放计算输出的图片宽度及高度
                    double rate1 = ((double) img.getWidth(null)) / (double) outputSize + 0.1;
                    double rate2 = ((double) img.getHeight(null)) / (double) outputSize + 0.1;
                    // 根据缩放比率大的进行缩放控制
                    double rate = rate1 > rate2 ? rate1 : rate2;
                    newWidth = (int) (((double) img.getWidth(null)) / rate);
                    newHeight = (int) (((double) img.getHeight(null)) / rate);
                } else {
                    newWidth = outputSize; // 输出的图片宽度
                    newHeight = outputSize; // 输出的图片高度
                }
                Logger.debug(PicCompressUtil.class,"begin create compress image:"+inputFileName);
                BufferedImage buffi = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);

                /*
                 * Image.SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的
                 * 优先级比速度高 生成的图片质量比较好 但速度慢
                 * 不可用sun包下的FileOutputStream输出，服务器上使用openjdk不支持该类
                 */
                Graphics g = buffi.getGraphics();
                g.drawImage(img.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH), 0, 0, null);
                g.dispose();
                ImageIO.write(buffi,"jpg",new File(outputDir + outputFileName));
            }
        } catch (IOException ex) {
            Logger.error(PicCompressUtil.class, "Exception while compress pic, {}", ex);
        } catch (Exception e){
            Logger.debug(PicCompressUtil.class,"unknow exception:"+e.getMessage());
            e.printStackTrace();
        }
        return "ok";
    }

    /**
     * 同路径下重命名压缩图片
     *
     * @param picDir
     * @param inputFileName
     * @param outputFileName
     * @return
     */
    public String compressPic(String picDir, String inputFileName, String outputFileName) {
        // 输入图路径
        this.inputDir = picDir;
        // 输出图路径
        this.outputDir = picDir;
        // 输入图文件名
        this.inputFileName = inputFileName;
        // 输出图文件名
        this.outputFileName = outputFileName;
        return compressPic();
    }

    /**
     * 同路径下对一个文件压缩不同尺寸比例图片
     *
     * @param picDir
     * @param inputFileName
     * @param compressSize
     * @return
     */
    public String[] compressPic(String picDir, String inputFileName, String[] compressSize) {
        String[] res = new String[compressSize.length];
        //输入图路径
        this.inputDir = picDir;
        //输出图路径
        this.outputDir = picDir;
        //输入图文件名
        this.inputFileName = inputFileName;

        for (int i = 0; i < compressSize.length; i++) {
            int size = Integer.parseInt(compressSize[i]);
//            String[] picName = inputFileName.split("\\.");
            //输出图文件名
            this.outputFileName = compressSize[i] + "_" + inputFileName;
//            Logger.debug(PicCompressUtil.class,"outputFileName:"+this.outputFileName);
            //设置压缩大小
            setWidthAndHeight(size);
            res[i] = compressPic();
        }
        return res;
    }

    public String compressPic(String inputDir, String outputDir, String inputFileName, String outputFileName, int size, boolean gp) {
        // 输入图路径
        this.inputDir = inputDir;
        // 输出图路径
        this.outputDir = outputDir;
        // 输入图文件名
        this.inputFileName = inputFileName;
        // 输出图文件名
        this.outputFileName = outputFileName;
        // 设置图片长宽
        setWidthAndHeight(size);
        // 是否是等比缩放 标记
        this.proportion = gp;
        return compressPic();
    }

    /**
     * * 将图片文件输出到指定的路径，并可设定压缩质量
     *
     * @param outImgPath
     * @param newImg
     * @param per
     * @author cevencheng
     */
//    private static void outImage(String outImgPath, BufferedImage newImg, float per) {
//        // 判断输出的文件夹路径是否存在，不存在则创建
//        File file = new File(outImgPath);
//        if (!file.getParentFile().exists()) {
//            file.getParentFile().mkdirs();
//        }
//        // 输出到文件流
//        FileOutputStream fos = null;
//        try {
//            fos = new FileOutputStream(outImgPath);
////            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fos);
////            JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(newImg);
//        // 压缩质量
////            jep.setQuality(per, true);
////            encoder.encode(newImg, jep);
////            fos.close();
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        } finally {
//            if (fos != null) {
//                try {
//                    fos.close();
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            }
//        }
//    }


    /**
     * 图片剪切工具方法
     *
     * @param srcfile 源图片
     * @param outfile 剪切之后的图片
     * @param x 剪切顶点 X 坐标
     * @param y 剪切顶点 Y 坐标
     * @param width 剪切区域宽度
     * @param height 剪切区域高度
     *
     * @throws IOException
     * @author cevencheng
     */

    public static void cut(File srcfile, File outfile, int x, int y, int width, int height) throws IOException {
        FileInputStream is = null;
        ImageInputStream iis = null;
        try {
        // 读取图片文件
            is = new FileInputStream(srcfile);
        /*
        * 返回包含所有当前已注册 ImageReader 的 Iterator，这些 ImageReader 声称能够解码指定格式。
        * 参数：formatName - 包含非正式格式名称 .（例如 "jpeg" 或 "tiff"）等 。
        */
            Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName("jpg");
            ImageReader reader = it.next();
        // 获取图片流
            iis = ImageIO.createImageInputStream(is);
        /*
        * <p>iis:读取源.true:只向前搜索 </p>.将它标记为 ‘只向前搜索’。.
        * 此设置意味着包含在输入源中的图像将只按顺序读取，可能允许 reader 避免缓存包含与以前已经读取的图像关联的数据的那些输入部分。
        */
            reader.setInput(iis, true);
        /*
        * <p>描述如何对流进行解码的类<p>.用于指定如何在输入时从 Java Image I/O
        * 框架的上下文中的流转换一幅图像或一组图像。用于特定图像格式的插件 将从其 ImageReader 实现的
        * getDefaultReadParam 方法中返回 ImageReadParam 的实例。
        */
//            ImageReadParam param = reader.getDefaultReadParam();
        /*
        * 图片裁剪区域。Rectangle 指定了坐标空间中的一个区域，通过 Rectangle 对象
        * 的左上顶点的坐标（x，y）、宽度和高度可以定义这个区域。
        */
            Rectangle rect = new Rectangle(x, y, width, height);
        // 提供一个 BufferedImage，将其用作解码像素数据的目标。
//            param.setSourceRegion(rect);
        /*
        * 使用所提供的 ImageReadParam 读取通过索引 imageIndex 指定的对象，并将 它作为一个完整的
        * BufferedImage 返回。
        */
//            BufferedImage bi = reader.read(0, param);
        // 保存新图片
//            ImageIO.write(bi, "jpg", outfile);
        } finally {
            if (is != null) {
                is.close();
            }
            if (iis != null) {
                iis.close();
            }
        }
    }

    // main测试
    // compressPic(大图片路径,生成小图片路径,大图片文件名,生成小图片文名,生成小图片宽度,生成小图片高度,是否等比缩放(默认为true))
    public static void main(String[] arg) {
        PicCompressUtil mypic = new PicCompressUtil();
//        Logger.debug(PicCompressUtil.class,"输入的图片大小：" + mypic.getPicSize("/Users/valentina/Downloads/142355165866771.jpg")/1024 + "KB");
//        int count = 0; // 记录全部图片压缩所用时间
//        String[] size = {"1280","360","240","60"};
//            int start = (int) System.currentTimeMillis();   // 开始时间
//            mypic.compressPic("/Users/valentina/Downloads/", "142355165866771.jpg", size);
//            int end = (int) System.currentTimeMillis(); // 结束时间
//            int re = end-start; // 图片生成处理时间
//        Logger.debug(PicCompressUtil.class,"总共用了：" + re + "毫秒");
        Logger.debug(PicCompressUtil.class, "" + PicCompressUtil.getPicWH("/Users/valentina/IdeaProjects/bwMall/output/bwmall-merchant/bwmall-merchant-1.0.0-SNAPSHOT/temp/" + "142365506495903.jpg"));

    }

}
